/**
 * GB28181服务程序
 */
const xml2js        = require('xml2js');
const digest        = require('sip/digest');
const config        = require('./sip_config');
const log4js        = require('./sip_log');
const logger        = log4js.getLogger('info');

const realm         = config.sip.server.realm; 

// 设备信息
let registry = config.registry;

/**
 * 封装发送的命令
 */
let command={
    // 公用sip对象
    sip:null,
    /**
    * 发送请求目录 命令
    */
    catalog: function(rs,deviceId){
      //TODO: 这个SN以后看怎么赋值才合理
      let SN=1;
      const json = {
        Query: {
              CmdType: 'Catalog',
              SN: SN,
              DeviceID: deviceId
          }
      };
      const builder = new xml2js.Builder();
      const content = builder.buildObject(json);
  
      const username = this.sip.parseUri(rs.headers.to.uri).user;
      // 从via解析摄像头的ip 端口
      const via = this.sip.parseUri(rs.headers.via)[0];
      let cseq  = rs.headers.cseq;
      cseq.method = 'MESSAGE';
      let res = {
        method:'MESSAGE',
        uri: 'sip:' + username + '@' + via.host + ':' + via.port,
        version:rs.version,
        headers:{
          via        : rs.headers.via,
          from      : rs.headers.from, 
          to        : rs.headers.to, 
          'call-id' : rs.headers['call-id'],
          cseq:cseq,
          'Content-Type':'Application/MANSCDP+xml',
          'expires':'3600',
          'Max-Forwards':70
        },
        content:content
      };
  
      logger.info(res);
      this.sip.send(res);
    },
    /**
     * 请求目录回应
     * @param {*} rq 
     * @param {*} result 
     */
    catalogAck:function(rq,DeviceList){
      if(DeviceList){
        for(let s in DeviceList[0].Item){
          let temp = DeviceList[0].Item[s];
          let exists = config.devices.indexOf(temp)>-1;
          if(!exists) {
            config.devices.push(temp);
          }
        }
      }
      this.sip.send(this.sip.makeResponse(rq,200,'OK'));
    },
    /**
    * 接收注册信息，并完成授权过程
    */
    register:function(rq){
      let username = this.sip.parseUri(rq.headers.to.uri).user;

      let userinfo = registry[username];
      // 如果不需要认证，生成用户信息
      if(!config.authentication && !userinfo){
        registry[username] = {password:config.sip.server.password,online:false};
        userinfo = registry[username];
      }
      if(!userinfo) {
        logger.error('没有登记的用户 禁止授权:' , username);
        let session = {realm: realm};
        this.sip.send(digest.challenge(session, this.sip.makeResponse(rq, 401, 'Unauthorized')));
        return;
      }
      else {
        userinfo.session = userinfo.session || {realm: realm};
        if(!digest.authenticateRequest(userinfo.session, rq, {user: username, password: userinfo.password})) {
          let ret0 = digest.challenge(userinfo.session, this.sip.makeResponse(rq, 401, 'Unauthorized'));
          this.sip.send(ret0);
        }
        else {
          // 完成授权
          userinfo.contact = rq.headers.contact;
          let rs = this.sip.makeResponse(rq, 200, 'Ok');
          this.sip.send(rs);
          logger.info('请求设备目录');
          registry[username].online=true;
          command.catalog(rq,username);
        }
      }
    },
    /**
    * 发送invite请求
    */
    invite:function(rs,target){
      let userinfo = registry[target];
      
      if(userinfo ) { //&& Array.isArray(userinfo.contact) && userinfo.contact.length > 0
        let content = 'v=0\r\n'+
          'o=fxdigital 0 0 IN IP4 ' + config.sip.server.ip + '\r\n' +
          's=Play\r\n'+
          'c=IN IP4 ' + config.sip.server.ip + '\r\n'+
          't=0 0\r\n'+
          'm=video ' + config.sip.media.port + ' RTP/AVP 96 97 98\r\n' + 
          'a=sendrecv\r\n'+
          'a=rtpmap:96 PS/90000\r\n'+
          'a=rtpmap:97 MPEG4/90000\r\n'+
          'a=rtpmap:98 H264/90000\r\n' +
          'y=0000000003\r\n'
          ;

        // 从via解析摄像头的ip 端口
        const via = this.sip.parseUri(rs.headers.via)[0];
        var via1  = JSON.parse( JSON.stringify(via));

        via1.host = config.sip.server.ip;
        via1.port = config.sip.server.port;
        via1.params.received=config.sip.server.ip;
        let cseq  = rs.headers.cseq;
        cseq.method = 'INVITE';
        let res   = {
          method  : cseq.method,
          uri     : 'sip:' + target + '@' + via.host + ':' + via.port,
          version : rs.version,
          headers : {
            via      : [[via1]],
            from     : {uri: 'sip:' + config.sip.server.account + '@' + config.sip.server.realm,params:{tag:config.rstring()}}, 
            to       : {uri: 'sip:' + '34020000001110000001' + '@' + via.host+':' + via.port},  //TODO: 这里暂时写死
            'call-id': rs.headers['call-id'],
            cseq:cseq,
            'Content-Type':'Application/SDP',
            'expires':'3600',
            'Max-Forwards':70,
            'User-Agent':'nodejs gb server',
            contact  : [{uri:'sip:' + config.sip.server.account + '@' + config.sip.server.ip + ':' + config.sip.server.port}],
            subject  : target +':1' + ',' + config.sip.server.account + ':0'
          },
          content:content
        };
    
        logger.info(res);
        this.sip.send(res);
      }
      else {
        logger.error('username',target,userinfo);
        this.sip.send(this.sip.makeResponse(rs, 404, 'Not Found'));
      }
    },
    /**
     * 回应心跳
     * @param {*} rq 
     */
    keepalive:function(rq){
      // 心跳
      const rs = this.sip.makeResponse(rq,200,'OK');
      const username = this.sip.parseUri( rq.headers.from.uri).user;
      config.registry[username].online  = true;
      config.registry[username].last    = (new Date()).getTime();
      this.sip.send(rs);
    },
    /**
     * 回应invite
     * @param {*} rs 
     * @param {*} target 
     */
    ack:function(rs){
      let cseq = rs.headers.cseq;
      cseq.method = 'ACK';
      let res = {
        method:'ACK',
        uri: rs.headers.to.uri,
        headers:{
          via      : [],
          from     : {uri: 'sip:' + config.sip.server.account + '@' + config.sip.server.realm , params:rs.headers.from.params}, 
          to       : rs.headers.to, 
          'call-id': rs.headers['call-id'],
          cseq:cseq,
          'Max-Forwards':70,
          'User-Agent':'nodejs gb server',
          contact  : [{uri:'sip:' + config.sip.server.account + '@' + config.sip.server.ip + ':' + config.sip.server.port}],
        }
      };
      this.sip.send(res);
    }
  };

module.exports = command;
